/*
 * Created by Jaren at 2021/11/29 8:56
 */
import 'dart:typed_data';

import 'package:inmotion_protocol/base/base_factory.dart';
import 'package:inmotion_protocol/common/compact.dart';
import 'package:inmotion_protocol/common/exceptions.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/lorin/constant.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/euc_message_factory.dart';
import 'package:inmotion_protocol/lorin/lorin_message.dart';
import 'package:inmotion_protocol/util/byte_util.dart';
import 'package:inmotion_protocol/util/version.dart';

class V11MessageFactory extends EucLorinSpecialMessageFactory<_V11Cmd> implements BMSLogMsgFactoryTrait<LorinMessage>, FullBMSFeatureMsgFactoryTrait<LorinMessage> {
  V11MessageFactory(ProductProperty productProperty) : super(productProperty);

  @override
  void initCompact(int apiVersion, VersionWrapper version) {
    if (productProperty.model.isV11Y()) {
      compact = _V11YCmdDefault();
    } else {
      String hmicVersion = version.getAppVersionByDevice(Constant.deviceEUCV11HMIC);
      if (VersionUtils.higherOrEquals(hmicVersion, VersionConstant.v11Hmic1228)) {
        compact = _V11CmdV137();
      } else {
        compact = _V11CmdDefault();
      }
    }
  }

  @override
  LorinMessage genSetSpeedLimitMsg(int speedLimit, [int? speedLimit2]) {
    if (productProperty.model.isV11Y()) {
      return genSpecialOne2OneWriteMsg(compact!.speedLimitCmd(), ByteUtil.buildBytes(ByteUtil.num2BytesLe(speedLimit, 2), ByteUtil.num2BytesLe(0, 2)));
    }
    return super.genSetSpeedLimitMsg(speedLimit);
  }

  LorinMessage genFanOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(compact!.fanCmd(), Uint8ClampedList.fromList([on ? 1 : 0]));
  }

  LorinMessage genRequestFanManualStateMsg() {
    return genSpecialOne2OneReadMsg(compact!.fanCmd());
  }

  LorinMessage genFanQuietModeOnOffMsg(bool on) {
    return genSpecialOne2OneWriteMsg(compact!.fanQuietModeCmd(), Uint8ClampedList.fromList([on ? 1 : 0]));
  }

  LorinMessage genDisableChargeDangerAlertMsg() {
    return genSpecialOne2OneWriteMsg(compact!.disableChargeDangerAlertCmd(), Uint8ClampedList.fromList([1]));
  }

  @override
  LorinMessage genPlaySoundItemMsg(int index) {
    if (productProperty.model.isV11Y()) return genSpecialOne2OneWriteMsg(compact!.playSoundItemCmd(), Uint8ClampedList.fromList([2, 100]));
    return super.genPlaySoundItemMsg(index);
  }

  @override
  LorinMessage genRequestBMSRealTimeInfoMsg(int target) {
    return genSpecialMany2ManyReadMsg(null, target, (compact! as _V11YCmdDefault).bmsRealTimeInfoCmd());
  }

  @override
  LorinMessage genRequestBMSFixedInfoMsg(int target) {
    _checkFullBMSFeatureCmdTrait();
    return genSpecialMany2ManyReadMsg(null, target, (compact! as FullBMSFeatureCmdTrait).bmsFixedInfoCmd());
  }

  @override
  LorinMessage genRequestBMSCellsVoltageInfoMsg(int target) {
    _checkFullBMSFeatureCmdTrait();
    return genSpecialMany2ManyReadMsg(null, target, (compact! as FullBMSFeatureCmdTrait).bmsCellsVoltageCmd());
  }

  @override
  LorinMessage genRequestBMSDateMsg(int target) {
    _checkFullBMSFeatureCmdTrait();
    return genSpecialMany2ManyReadMsg(null, target, (compact! as FullBMSFeatureCmdTrait).bmsDateCmd());
  }

  @override
  LorinMessage genRequestBMSLogMsg(int target, int index) {
    _checkFullBMSFeatureCmdTrait();
    return genSpecialMany2ManyReadMsg(null, target, (compact! as _V11YCmdDefault).bmsLogCmd(), ByteUtil.num2BytesLe(index, 4));
  }

  @override
  LorinMessage genRequestBMSLogCountMsg(int target) {
    _checkFullBMSFeatureCmdTrait();
    return genSpecialMany2ManyReadMsg(null, target, (compact! as _V11YCmdDefault).bmsLogCmd(), ByteUtil.num2BytesLe(0xFFFFFFFF, 4));
  }

  _checkFullBMSFeatureCmdTrait([bool throwException = true]) {
    if (compact! is! FullBMSFeatureCmdTrait) {
      if (throwException) throw NotSupportException('');
      return false;
    }
    return true;
  }
}

abstract class _V11Cmd extends EucCmdCompact {
  int fanCmd();

  int fanQuietModeCmd();

  int disableChargeDangerAlertCmd() {
    return 0;
  }
}

class _V11CmdDefault extends _V11Cmd {
  @override
  int autoHeadlightCmd() {
    return 47;
  }

  @override
  int autoHeadlightBrightnessThrCmd() {
    return 42;
  }

  @override
  int brightnessOfHeadlightCmd() {
    return 43;
  }

  @override
  int fanCmd() {
    return 83;
  }

  @override
  int fanQuietModeCmd() {
    return 56;
  }

  @override
  int headlightOnOffCmd() {
    return 64;
  }

  @override
  int lightEffectIdCmd() {
    /// not support
    return 0;
  }

  @override
  int remainderRangeEstimateCmd() {
    return 61;
  }

  @override
  int soundWaveCmd() {
    return 57;
  }

  @override
  int soundWaveSensitivityCmd() {
    return 0;
  }

  @override
  int speedingBrakingCmd() {
    return 0;
  }

  @override
  int assistBalanceCmd() {
    return 0;
  }

  @override
  int speedingBrakingSensitivityCmd() {
    return 62;
  }

  @override
  int transportationModeCmd() {
    return 50;
  }

  @override
  int usbPowerCmd() {
    return 60;
  }

  @override
  int calibrateImuCmd() {
    return 66;
  }

  @override
  int lightEffectModeCmd() {
    return 45;
  }

  @override
  int deviceNameCmd() {
    return 0;
  }

  @override
  int passwordCmd() {
    return 0;
  }

  @override
  int passwordTypeCmd() {
    return 0;
  }

  @override
  int bermAngleModeCmd() {
    return 0;
  }
}

class _V11CmdV137 extends _V11CmdDefault {
  @override
  int headlightOnOffCmd() {
    return 80;
  }

  @override
  int playSoundItemCmd() {
    return 81;
  }

  @override
  int calibrateImuCmd() {
    return 82;
  }

  @override
  int fanCmd() {
    return 83;
  }

  @override
  int autoHeadlightCmd() {
    return 0;
  }

  @override
  int disableChargeDangerAlertCmd() {
    return 84;
  }

  @override
  int speedingBrakingCmd() {
    return 62;
  }

  @override
  int speedingBrakingSensitivityCmd() {
    return 63;
  }

  @override
  int assistBalanceCmd() {
    return 64;
  }
}

class _V11YCmdDefault extends _V11Cmd implements FullBMSFeatureCmdTrait {
  @override
  int autoHeadlightCmd() {
    return 47;
  }

  @override
  int autoHeadlightBrightnessThrCmd() {
    return 42;
  }

  @override
  int brightnessOfHeadlightCmd() {
    return 43;
  }

  @override
  int deviceNameCmd() {
    return 12;
  }

  @override
  int headlightOnOffCmd() {
    return 80;
  }

  @override
  int lightEffectIdCmd() {
    return 45;
  }

  @override
  int passwordCmd() {
    return 10;
  }

  @override
  int passwordTypeCmd() {
    return 11;
  }

  @override
  int remainderRangeEstimateCmd() {
    return 61;
  }

  @override
  int soundWaveCmd() {
    return 0;
  }

  @override
  int soundWaveSensitivityCmd() {
    return 0;
  }

  @override
  int speedingBrakingCmd() {
    return 62;
  }

  @override
  int speedingBrakingSensitivityCmd() {
    return 63;
  }

  @override
  int usbPowerCmd() {
    return 60;
  }

  int queryCalibrationResultCmd() {
    return 66;
  }

  @override
  int lightEffectModeCmd() {
    return 45;
  }

  @override
  int bmsCellsVoltageCmd() {
    return 2;
  }

  @override
  int bmsDateCmd() {
    return 3;
  }

  @override
  int bmsFixedInfoCmd() {
    return 4;
  }

  int bmsLogCmd() {
    return 5;
  }

  @override
  int bmsRealTimeInfoCmd() {
    return 1;
  }

  @override
  int playSoundItemCmd() {
    return 81;
  }

  @override
  int safeSpeedLimitCmd() {
    return 68;
  }

  @override
  int bermAngleModeCmd() {
    return 69;
  }

  @override
  int fanCmd() {
    return 56;
  }

  @override
  int fanQuietModeCmd() {
    return 83;
  }
}
